其他
Android筑基,Kotlin扩展函数详解
/ 今日科技快讯 /
近日,美国电动汽车制造商特斯拉股价下跌近7%,这让埃隆马斯克的个人财富再次不足2000亿美元。特斯拉股价去年11月曾超1240美元,如今已接近腰斩。虽然目前马斯克的个人财富处于去年8月26日以来的最低位,但其仍是全世界最富有的人。
/ 作者简介 /
本篇文章来自willwaywang6的投稿,文章主要分享了作者对Kotlin中扩展函数的理解使用,相信会对大家有所帮助!同时也感谢作者贡献的精彩文章。
willwaywang6的博客地址:
https://blog.csdn.net/willway_wang?type=blog
/ 前言 /
接触 Kotlin 的扩展函数有一段时间了,不过对这个知识的理解只是停留在顶层扩展函数而已。
在继续学习 Kotlin 的使用时,发现这样的理解是远远不够的,比如这些问题就不清楚:
扩展函数的本质是什么吗? 如何引用一个扩展函数? 成员扩展函数是什么,有什么用? 扩展函数类型和普通函数类型是什么,如何相互转换?
声明(顶层)扩展函数
fun String.lastChar(): Char {
return this.get(this.length - 1)
}
println("Kotlin".lastChar()) // 打印:n
}
fun String.lastChar(): Char {
return get(length - 1)
}
对扩展函数的深入理解
接收者类型就只是类或者接口吗?
var y: String? // 可空类型
var nullStringList: List<String?>
var stringNullList: List<String>?
var stringListList: List<List<String>>
return this?.get(0)
}
println("Kotlin".firstChar()) // 打印:K
println(null.firstChar()) // 打印:null
}
fun List<Int>.sum(): Int {
var sum: Int = 0
for (element in this) {
sum += element
}
return sum
}
fun List<Double>.sum(): Double {
var sum: Double = 0.0
for (element in this) {
sum += element
}
return sum
}
println(listOf(1, 2, 3).sum()) // 打印:6
println(listOf(1.1, 2.2, 3.3).sum()) // 打印:6.6
}
fun <T> List<T>.joinToString(): String {
val result = StringBuilder()
for ((index, element) in this.withIndex()) {
if (index > 0) result.append(", ")
result.append(element)
}
return result.toString()
}
println(listOf(1, 2, 3).joinToString()) // 1, 2, 3
println(listOf("a", "b", "c").joinToString()) // a, b, c
}
fun String.lastChar(): Char {
return this.get(this.length - 1)
}
public static final char lastChar(@NotNull String $this$lastChar) {
Intrinsics.checkNotNullParameter($this$lastChar, "$this$lastChar");
return $this$lastChar.charAt($this$lastChar.length() - 1);
}
}
从 Java 中如何调用扩展函数?
public static void main(String[] args) {
System.out.println(StringExtensionsKt.lastChar("Java"));
}
}
class Button: View()
fun Button.showOff() = println("Button extension showOff")
val buttonView: View = Button()
buttonView.showOff()
}
public static final void main() {
View buttonView = (View)(new Button());
ViewExtenionsKt.showOff(buttonView);
}
}
public static final void showOff(@NotNull View $this$showOff) {
Intrinsics.checkNotNullParameter($this$showOff, "$this$showOff");
String var1 = "View extension showOff";
boolean var2 = false;
System.out.println(var1);
}
public static final void showOff(@NotNull Button $this$showOff) {
Intrinsics.checkNotNullParameter($this$showOff, "$this$showOff");
String var1 = "Button extension showOff";
boolean var2 = false;
System.out.println(var1);
}
}
open fun showOff() {
println("View member showOff" )
}
}
class Button: View() {
override fun showOff() {
println("Button member showOff" )
}
}
val buttonView: View = Button()
buttonView.showOff()
}
fun String.lastChar(): Char {
return this.get(this.length - 1)
}
fun greetings(message: String) {
println("Hello, $message")
}
val greeting = ::greetings
}
val greeting: (message: String) -> Unit = ::greetings
}
val greeting: (String) -> Unit = ::greetings
}
println("Hello, $this")
}
fun String?.greeting3() {
println("Hello, $this")
}
val greeting2 = String::greetings2
val greeting3 = String?::greeting3
}
greeting3("Kotlin")
greeting3(null)
greeting3("Kotlin")
greeting3(null) // 编译报错:Null can not be a value of a non-null type String
// allowed on a nullable receiver of type String?
val greeting2: Any = String?::greetings2
/*
编译报错:
Platform declaration clash: The following declarations have the same JVM signature (greetings(Ljava/lang/String;)V):
public fun greetings(message: String): Unit defined in com.kotlin.lib._1_topextensionfunction in file Util.kt
public fun String.greetings(): Unit defined in com.kotlin.lib._1_topextensionfunction in file Util.kt
*/
fun greetings(message: String) { // 函数声明下有红色波浪线
println("Hello, $message")
}
fun String.greetings() { // 函数声明下有红色波浪线
println("Hello, $this")
}
public static final void greetings(@NotNull String $this$greetings) {
Intrinsics.checkNotNullParameter($this$greetings, "message");
String var1 = "Hello, " + $this$greetings;
boolean var2 = false;
System.out.println(var1);
}
public static final void greetings(@NotNull String $this$greetings) {
Intrinsics.checkNotNullParameter($this$greetings, "message");
String var1 = "Hello, " + $this$greetings;
boolean var2 = false;
System.out.println(var1);
}
}
val greeting3: Any = String?::greeting3
val greeting3: (String?) -> Unit = String?::greeting3
val greeting2: (String) -> Unit = String::greetings2
greeting2.invoke("Kotlin") // 打印:Hello, Kotlin
greeting2("Android") // 打印:Hello, Android
}
fun isValid(): Boolean {
return number.length == 11 && number.all { it.isDigit() }
}
}
class PhoneBook {
fun verify(phoneNumber: PhoneNumber): Boolean {
return phoneNumber.check()
}
// check 是一个成员扩展函数
fun PhoneNumber.check(): Boolean {
printPhoneNumber(this.number) // printPhoneNumber 是由分发接收者,即 PhoneBook 对象来调用的。
return isValid() // isValid() 是由扩展接收者,即 PhoneNumber 对象来调用的。
}
private fun printPhoneNumber(number: String) {
println("PhoneBook: $number")
}
}
fun main() {
println(PhoneBook().verify(PhoneNumber("13912345678")))
}
true
对成员扩展函数的深入理解
当分发接收者和扩展接收者的成员之间出现命名冲突时,会优先使用哪个成员?
fun isValid(): Boolean {
return number.length == 11 && number.all { it.isDigit() }
}
fun printPhoneNumber(number: String) {
println("PhoneNumber: $number")
}
}
true
this@PhoneBook.printPhoneNumber(this.number)
return isValid()
}
true
class Derived : Base() { }
open class BaseCaller {
open fun Base.printFunctionInfo() {
println("Base extension function in BaseCaller")
}
open fun Derived.printFunctionInfo() {
println("Derived extension function in BaseCaller")
}
fun call(b: Base) {
b.printFunctionInfo() // call the extension function
}
}
class DerivedCaller: BaseCaller() {
override fun Base.printFunctionInfo() {
println("Base extension function in DerivedCaller")
}
override fun Derived.printFunctionInfo() {
println("Derived extension function in DerivedCaller")
}
}
fun main() {
BaseCaller().call(Base())
DerivedCaller().call(Base())
DerivedCaller().call(Derived())
}
Base extension function in DerivedCaller
Base extension function in DerivedCaller
class Base {
}
final class Derived extends Base {
}
class BaseCaller {
public void printFunctionInfo(@NotNull Base base) {
System.out.println("Base extension function in BaseCaller");
}
public void printFunctionInfo(@NotNull Derived derived) {
System.out.println("Derived extension function in BaseCaller");
}
public final void call(@NotNull Base b) {
this.printFunctionInfo(b);
}
}
final class DerivedCaller extends BaseCaller {
public void printFunctionInfo(@NotNull Base base) {
System.out.println("Base extension function in DerivedCaller");
}
public void printFunctionInfo(@NotNull Derived derived) {
System.out.println("Derived extension function in DerivedCaller");
}
}
public final class CallerKt {
public static void main(String[] var0) {
new BaseCaller().call(new Base());
new DerivedCaller().call(new Base());
new DerivedCaller().call(new Derived());
}
}
Base extension function in DerivedCaller
Base extension function in DerivedCaller
成员扩展函数与顶层扩展函数的区别是什么?
扩展函数类型
println(block(str))
}
fun String.lastChar(): Char {
return this.get(this.length - 1)
}
val lastChar: (String) -> Char = String::lastChar
printChar1("Kotlin") {
lastChar(it)
}
}
println(str.block())
}
println(str.block())
}
val lastChar: (String) -> Char = String::lastChar
printChar1("Kotlin") {
lastChar(it)
}
printChar2("Android") {
// 可以看到,这里就可以和扩展函数一样的方式调用了。
this.lastChar()
}
}
d
val greeting2: (String) -> Unit = String::greetings2
greeting2.invoke("Kotlin")
greeting2("Android") // 以普通函数的方式来调用
// 使用扩展函数类型
val greeting22: String.() -> Unit = String::greetings2
"Kotlin".greeting22() // 以扩展函数的方式来调用
https://github.com/jhwsx/BlogCodes/tree/master/KotlinExtensionFunctionStudy